package com.xmeta.opensdk.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.xmeta.opensdk.component.InvokingMethodProperties;
import com.xmeta.opensdk.component.InvokingProperties;
import com.xmeta.opensdk.component.RestTemplateComponent;
import com.xmeta.opensdk.constant.BaseParameterConstant;
import com.xmeta.opensdk.enums.RespEnum;
import com.xmeta.opensdk.model.dto.*;
import com.xmeta.opensdk.model.vo.*;
import com.xmeta.opensdk.service.InvokingService;
import com.xmeta.opensdk.util.AESUtil;
import com.xmeta.opensdk.util.RSASignUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class InvokingServiceImpl implements InvokingService {

    @Resource
    private InvokingProperties invokingProperties;

    @Resource
    private InvokingMethodProperties invokingMethodProperties;

    @Resource
    private RestTemplateComponent restTemplateComponent;

    @Override
    public CommonResp syncUser(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());
        //取出objEncrypt中的数据
        SyncUserInfoDTO syncUserInfoDTO = JSONUtil.toBean(decode, SyncUserInfoDTO.class);

        //TODO 业务处理

        //aes加密返回objEncrypt

        //封装响应参数
        SyncUserInfoVO syncUserInfoVO = new SyncUserInfoVO();
        syncUserInfoVO.setUserId("");
        syncUserInfoVO.setWalletHash("");
        String idCard = "xxx".toLowerCase().trim();
        String str = "phone=" + "1111" + "&username=" + "xxxx" + "&idcard=" + idCard;
        String md5Hex1 = DigestUtil.md5Hex(str);
        syncUserInfoVO.setVerifySign(md5Hex1);
        String objEncrypt = JSONUtil.toJsonStr(syncUserInfoVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getSyncUserInfo());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp goodsList(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());
        //取出objEncrypt中的数据
        GoodsListDTO goodsListDTO = JSONUtil.toBean(decode, GoodsListDTO.class);

        //TODO 业务处理

        //封装响应参数
        List<GoodsListVO> goodsListVOS = new ArrayList<>();
        GoodsListVO goodsListVO = new GoodsListVO();
        goodsListVOS.add(goodsListVO);
        String objEncrypt = JSONUtil.toJsonStr(goodsListVOS);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getGoodsList());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp goodsVerify(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());
        //取出objEncrypt中的数据
        GoodsVerifyDTO goodsVerifyDTO = JSONUtil.toBean(decode, GoodsVerifyDTO.class);

        //TODO 业务处理

        //封装响应参数
        List<GoodsVerifyVO> goodsVerifyVOS = new ArrayList<>();
        GoodsVerifyVO goodsVerifyVO = new GoodsVerifyVO();
        goodsVerifyVOS.add(goodsVerifyVO);
        String objEncrypt = JSONUtil.toJsonStr(goodsVerifyVOS);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getVerify());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp goodsTransfer(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());

        //取出objEncrypt中的数据
        GoodsTransferDTO goodsTransferDTO = JSONUtil.toBean(decode, GoodsTransferDTO.class);

        //TODO 业务处理

        //封装响应参数
        GoodsTransferVO goodsTransferVO = new GoodsTransferVO();
        GoodsTransferVO.GoodsTransferVOList goodsTransferVOList = new GoodsTransferVO.GoodsTransferVOList();
        List<GoodsTransferVO.GoodsTransferVOList> goodsTransferVOLists = new ArrayList<>();
        goodsTransferVOLists.add(goodsTransferVOList);
        goodsTransferVO.setGoodsList(goodsTransferVOLists);

        String objEncrypt = JSONUtil.toJsonStr(goodsTransferVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getTransferGift());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp goodsTransferConfirm(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());

        //取出objEncrypt中的数据
        GoodsTransferConfirmDTO goodsTransferConfirmDTO = JSONUtil.toBean(decode, GoodsTransferConfirmDTO.class);

        //TODO 业务处理

        //封装响应参数
        GoodsTransferConfirmVO goodsTransferConfirmVO = new GoodsTransferConfirmVO();
        GoodsTransferConfirmVO.GoodsTransferConfirmList goodsTransferVOList = new GoodsTransferConfirmVO.GoodsTransferConfirmList();
        List<GoodsTransferConfirmVO.GoodsTransferConfirmList> goodsTransferConfirmLists = new ArrayList<>(10);
        goodsTransferConfirmLists.add(goodsTransferVOList);
        goodsTransferConfirmVO.setGoodsList(goodsTransferConfirmLists);

        String objEncrypt = JSONUtil.toJsonStr(goodsTransferConfirmVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getTransferConfirm());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp goodsPutAway(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());

        //取出objEncrypt中的数据
        GoodsPutAwayDTO goodsTransferConfirmDTO = JSONUtil.toBean(decode, GoodsPutAwayDTO.class);

        //封装响应参数
        GoodsPutAwayVO goodsPutAwayVO = new GoodsPutAwayVO();
        GoodsPutAwayVO.GoodsPutAwayVOList goodsPutAwayVOList = new GoodsPutAwayVO.GoodsPutAwayVOList();
        List<GoodsPutAwayVO.GoodsPutAwayVOList> goodsPutAwayVOLists = new ArrayList<>(10);
        goodsPutAwayVOLists.add(goodsPutAwayVOList);
        goodsPutAwayVO.setGoodsList(goodsPutAwayVOLists);

        String objEncrypt = JSONUtil.toJsonStr(goodsPutAwayVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getPutAway());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public CommonResp receiveVerify(CommonReq commonReq) {

        verifyReq(commonReq, invokingProperties.getAesKey());
        String decode = AESUtil.decode(invokingProperties.getAesKey(), commonReq.getObjEncrypt());

        //取出objEncrypt中的数据
        ReceiveVerifyDTO receiveVerifyDTO = JSONUtil.toBean(decode, ReceiveVerifyDTO.class);

        //封装响应参数
        ReceiveVerifyVO receiveVerifyVO = new ReceiveVerifyVO();
        receiveVerifyVO.setMessage("xx");
        receiveVerifyVO.setStatus(1);

        String objEncrypt = JSONUtil.toJsonStr(receiveVerifyVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        //sign签名返回
        CommonResp commonResp = new CommonResp();
        commonResp.setMethod(invokingMethodProperties.getBuyerReceiveVerify());
        commonResp.setTimestamp(String.valueOf(System.currentTimeMillis()));
        commonResp.setNonce(IdUtil.simpleUUID());
        commonResp.setCode(RespEnum.SUCCESS.getK());
        commonResp.setMsg(RespEnum.SUCCESS.getV());
        commonResp.setObjEncrypt(objEncrypt);
        commonResp.setAppId(invokingProperties.getAppId());
        String s = encodeSign(commonResp);
        commonResp.setSign(s);
        return commonResp;
    }

    @Override
    public void archiveTransfer() {

        //TODO 业务处理

        //封装请求参数
        ArchiveTransferVO archiveTransferVO = new ArchiveTransferVO();
        archiveTransferVO.setAppId(invokingProperties.getAppId());
        ArchiveTransferVO.ArchiveTransferList archiveTransferList = new ArchiveTransferVO.ArchiveTransferList();
        List<ArchiveTransferVO.ArchiveTransferList> archiveTransferLists = new ArrayList<>(10);
        archiveTransferLists.add(archiveTransferList);
        archiveTransferVO.setArchiveList(archiveTransferLists);

        String objEncrypt = JSONUtil.toJsonStr(archiveTransferVO);
        objEncrypt = AESUtil.encode(invokingProperties.getAesKey(), objEncrypt);

        CommonReq commonReq = new CommonReq();
        commonReq.setObjEncrypt(objEncrypt);
        commonReq.setAppId(invokingProperties.getAppId());
        commonReq.setMethod(invokingMethodProperties.getArchive());
        commonReq.setNonce(IdUtil.simpleUUID());
        commonReq.setTimestamp(String.valueOf(System.currentTimeMillis()));
        String s = encodeSign(commonReq);
        commonReq.setSign(s);

        Object o = restTemplateComponent.postEntity(invokingProperties.getUrl(), JSONUtil.toJsonStr(commonReq));
        ArchiveTransferDTO archiveTransferDTO = JSONUtil.toBean(JSONUtil.toJsonStr(o), ArchiveTransferDTO.class);

        //TODO 业务处理

    }


    private void verifyReq(CommonReq commonReq, String aesKey) {
        //校验签名
        if (!verifyReqSign(commonReq)) {
            //签名不匹配
        }

        //解密objEncrypt
        if (!verifyObjEncrypt(invokingProperties.getAesKey(), commonReq.getObjEncrypt())) {
            //解密错误
        }

    }


    /**
     * @param commonResp
     * @return
     */
    private String encodeSign(CommonResp commonResp) {
        Map<String, String> encodeSign = new HashMap<>(16);
        encodeSign.put(BaseParameterConstant.APPID, commonResp.getAppId());
        encodeSign.put(BaseParameterConstant.METHOD, commonResp.getMethod());
        encodeSign.put(BaseParameterConstant.NONCE, commonResp.getNonce());
        encodeSign.put(BaseParameterConstant.OBJ_ENCRYPT, commonResp.getObjEncrypt());
        encodeSign.put(BaseParameterConstant.TIMESTAMP, commonResp.getTimestamp());
        encodeSign.put(BaseParameterConstant.CODE, String.valueOf(commonResp.getCode()));
        encodeSign.put(BaseParameterConstant.MSG, commonResp.getMsg());
        String s = RSASignUtil.splicingParamString(encodeSign);
        return RSASignUtil.sign(invokingProperties.getAppPrivateKey(), s);
    }

    /**
     * @param commonReq
     * @return
     */
    private String encodeSign(CommonReq commonReq) {
        Map<String, String> encodeSign = new HashMap<>(16);
        encodeSign.put(BaseParameterConstant.APPID, commonReq.getAppId());
        encodeSign.put(BaseParameterConstant.METHOD, commonReq.getMethod());
        encodeSign.put(BaseParameterConstant.NONCE, commonReq.getNonce());
        encodeSign.put(BaseParameterConstant.OBJ_ENCRYPT, commonReq.getObjEncrypt());
        encodeSign.put(BaseParameterConstant.TIMESTAMP, commonReq.getTimestamp());
        String s = RSASignUtil.splicingParamString(encodeSign);
        return RSASignUtil.sign(invokingProperties.getAppPrivateKey(), s);
    }


    /**
     * 校验请求签名
     *
     * @param commonReq 公共请求
     * @return 校验成功失败
     */
    private boolean verifyReqSign(CommonReq commonReq) {
        Map<String, String> signVerifyMap = new HashMap<>(16);
        signVerifyMap.put(BaseParameterConstant.APPID, commonReq.getAppId());
        signVerifyMap.put(BaseParameterConstant.METHOD, commonReq.getAppId());
        signVerifyMap.put(BaseParameterConstant.NONCE, commonReq.getNonce());
        signVerifyMap.put(BaseParameterConstant.OBJ_ENCRYPT, commonReq.getObjEncrypt());
        signVerifyMap.put(BaseParameterConstant.TIMESTAMP, commonReq.getTimestamp());
        String selfSign = RSASignUtil.splicingParamString(signVerifyMap);

        return RSASignUtil.verify(invokingProperties.getPublicKey(), selfSign, commonReq.getSign());
    }

    /**
     * 校验objEncrypt
     *
     * @param aesKey     aesKey
     * @param objEncrypt 请求objEncrypt
     * @return 成功失败
     */
    private boolean verifyObjEncrypt(String aesKey, String objEncrypt) {
        try {
            AESUtil.decode(invokingProperties.getAesKey(), objEncrypt);
        } catch (Exception e) {
            //解密出错
            return false;
        }
        return true;
    }
}
